#!/usr/bin/env python

import cherrypy
import json
import time
import os
import git
import shutil

from app.git_tools import GitTools
from app.commits import Commits
from app.revisions import Revisions
from app.summary import Summary
from app.developers import Developers
from app.utils import output
from settings import STATIC_PATH, REPOS_PATH


class Giuseppe:
  @cherrypy.expose
  def clone(self, **params):
    """Clone remote GIT repository"""
    db = cherrypy.thread_data.db
    
    # Get cloning status
    if "status" in params:
      key = cherrypy.session.get('sessid')
      return output("OK", db.clone_status.find_one({"_id": key}))
      
    # Clear cloning status
    elif "clear_status" in params:
      key = cherrypy.session.get('sessid')
      db.clone_status.remove({"_id": key})
      return output("OK")
      
    # Download repository
    else:
      url = params["url"]
      name = params["name"]
      key = cherrypy.session.originalid
      cherrypy.session['sessid'] = key
      
      st = GitTools.clone_repo(name, url, key)
      return output(st)
      
  @cherrypy.expose
  def commits_info(self, name, since, until, **params):
    """Find commits in specified date range"""
    repo = GitTools.load_repo(name)
    if not repo:
      return output("NOT_EXIST")
    
    commits = []  
    for c in repo.iter_commits(since=int(since), until=int(until)):
      commits.append({
        "sha": c.hexsha,
        "datetime": c.committed_date,
        "author": c.committer.name,
        "message": c.message
      })
    
    return output(data=commits)

  @cherrypy.expose
  def commits(self, name, since, until, group):
    """Sum the daily commits in specified date range"""
    repo = GitTools.load_repo(name)
    if not repo:
      return output("NOT_EXIST")
    
    since = int(since)
    until = int(until)
    data = []
    
    if group == "daily":
      data = Commits.daily(repo, since, until)
    elif group == "weekday":
      data = Commits.weekday(repo, since, until)
    elif group == "hourly":
      data = Commits.hourly(repo, since, until)
    elif group == "monthly":
      data = Commits.monthly(repo, since, until)
      
    return output(data=data)
    
  @cherrypy.expose
  def project(self, a, **params):
    """List or delete projects"""
    db = cherrypy.thread_data.db
    data = None
    
    if a == "list":
      data = [p for p in db.projects.find().sort("name")]
      
    elif a == "delete":
      name = params["name"]
      db.projects.remove({"name": name})
      shutil.rmtree(REPOS_PATH + "/" + name)
      
    elif a == "update":
      name = params["name"]
      repo = GitTools.load_repo(name)
      if not repo:
        return output("NOT_EXIST")

      data = repo.git.pull()
      db.projects.update(
        {"name": name},
        {"$set": {"updated": time.time()}})
        
    elif a == "select":
      name = params["name"]
      db.projects.update(
        {"selected": True},
        {"$set": {"selected": False}})
      db.projects.update(
        {"name": name},
        {"$set": {"selected": True}})
    
    return output("OK", data)
      
  @cherrypy.expose
  def partial(self, name):
    """Read the content of partial a return it."""
    path = STATIC_PATH + "/" + name + ".html"
    if (not os.path.exists(path)):
      return output("NOT_EXIST")
    
    f = open(path, "r")
    content = f.read()
    f.close()
    return output(data=content)
    
  @cherrypy.expose
  def revisions(self, name):
    """Return last revisions of given project."""
    repo = GitTools.load_repo(name)
    if not repo:
      return output("NOT_EXIST")
    
    revs = Revisions.list(repo)
    return output(data=revs)
    
  @cherrypy.expose
  def browse_revision(self, name, sha, path):
    """List folder or read file of given revision."""
    repo = GitTools.load_repo(name)
    if not repo:
      return output("NOT_EXIST")
    
    # Load revision
    try:
      tree = git.Commit(repo, sha.decode("hex")).tree
    except:
      return output("BAD_REVISION")
      
    # Load path
    node = Revisions.navigate_path(tree, path)
    if node is None:
      return output("BAD_PATH")
    
    # List content of folder
    if node.type == "tree":
      data = Revisions.list_folder(node)
    # Read syntax-highlighted file
    else:
      data = Revisions.show_file(node)
    
    return output(data=data)
    
  @cherrypy.expose
  def summary(self, name, scope, section):
    """Brief stats about commits, developers, files, etc."""
    repo = GitTools.load_repo(name)
    if not repo:
      return output("NOT_EXIST")
      
    since, until = GitTools.timerange(repo, scope)
    data = []
    
    if section == "commits":
      data = Summary.commits(repo, since, until)
    elif section == "developers":
      data = Summary.developers(repo, since, until)
    elif section == "files":
      data = Summary.files(repo, since, until)
    
    return output(data=data)
    
  @cherrypy.expose
  def developers(self, name, since, until):
    """List of developers with commits counts"""
    repo = GitTools.load_repo(name)
    if not repo:
      return output("NOT_EXIST")
      
    since = int(since)
    until = int(until)
    data = Developers.list(repo, since, until)
  
    return output(data=data)
    